home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- TITLE IBM-PC Cluster Owner Program, Version 1.40, 21-Aug-1986
-
- ;
- ; Written By Steven Georgiades
- ;
- ; IBM-PC/XT Cluster Owner Program
- ; Will respond with the name of the file that owns the specified cluster.
- ;
- ; If you are using this program and find it of value, your
- ; contribution in any amount ($5.00 suggested) will be greatly
- ; appreciated. Makes checks payable to Steven M. Georgiades.
- ; Thank you.
- ;
- ; If you have any questions or comments about this or any other
- ; SMG program, call or write:
- ;
- ; Steven M. Georgiades
- ; 701-H South Hayward Street
- ; Anaheim, CA 92804
- ; (714) 826-9549
- ;
-
- CODE SEGMENT BYTE PUBLIC 'CODE'
-
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
-
- ORG 5CH
-
- FCB LABEL BYTE
-
- ORG 80H
-
- PARAM LABEL BYTE
-
- ORG 100H
-
- OWNER: JMP BEGIN
-
- CRLF DB 13,10,"$"
- DIGIT DB "0123456789ABCDEF"
- READERR DB "Error Reading Drive X:",7,13,10,"$"
- SIGNON DB "Owner, Version 1.40",13,10,10,"$"
-
- CLUSTMSG DB "Cluster XXXXX $"
- OWNERMSG DB "is Owned by $"
- BADMSG DB "is Marked as Bad",13,10,"$"
- FREEMSG DB "is not is Use by any File",13,10,"$"
- INVALID DB "does not Exist!",7,13,10,"$"
- LOSTMSG DB "Appears to be Lost!",7,13,10,"$"
- RESVMSG DB "is Reserved",13,10,"$"
-
- CLSTSEC DW ?
- CLSTTOT DW ?
- CLUST DW ?
- DIR_LEN DW ?
- DIRBUF DW ?
- DIRSEC DW ?
- DRIVE DB ?
- EOF DW 0FF8H
- FATSEC DW ?
- FATSIZE DB 3
- RDIR_LEN DW ?
- SECSIZE DW ?
- STARTSEC DW ?
-
- DIRNAME DB 14 DUP(0)
- FILESPEC DB "X:\"
- PATH DB "$",79 DUP(0)
- FILENAME DB 14 DUP(0)
-
- BEGIN: MOV AH,9 ; Output Sign-On Message
- MOV DX,OFFSET SIGNON
- INT 21H
- MOV AH,19H ; Get Default Drive Number
- INT 21H
- MOV DRIVE,AL ; and Save
- MOV SI,OFFSET PARAM ; Set up Pointer to Parameter
- LODSB ; Read Parameter Length
- CBW
- MOV BX,AX
- MOV BYTE PTR [SI][BX],0 ; Terminate Parameter String
- STRIP: LODSB ; Strip Off Leading Whitespace
- CMP AL,' '
- JE STRIP
- CMP AL,9
- JE STRIP
- OR AL,AL ; If End-of-Parameter,
- JZ RD_BOOT ; Continue Proccessing
- CMP AL,'/' ; If Switch, Process
- JE SWITCH
- DEC SI ; ReUse Last Character
- CALL GET_WORD ; Read Cluster Number (Hex)
- MOV CLUST,DX ; Save Cluster Number
- JMP SHORT STRIP ; Get Next Parameter
- SWITCH: LODSB ; Get Drive Letter
- SUB AL,'A' ; Convert to Drive Number
- MOV DRIVE,AL ; Save Drive Number
- JMP SHORT STRIP ; Get Next Paramter
- RD_BOOT: MOV AL,DRIVE ; Read Boot Record
- MOV CX,1
- MOV DX,0
- MOV BX,OFFSET FATBUF
- INT 25H
- JNC BOOT_OK
- JMP RDERROR ; If Error, Say So
- BOOT_OK: POPF
- MOV AX,FATBUF[11] ; Read Sector Size
- MOV SECSIZE,AX ; and Save
- MOV AL,BYTE PTR FATBUF[13] ; Read Sectors per Cluster
- XOR AH,AH
- MOV CLSTSEC,AX ; and Save
- MOV CX,FATBUF[14] ; Read # of Reserved Sectors
- MOV AL,BYTE PTR FATBUF[16] ; Read # of FAT's
- XOR AH,AH ; Convert to Word
- MOV BX,FATBUF[22] ; Read Sectors per FAT
- MOV FATSEC,BX
- MUL BX ; Calculate Total FAT Sectors
- ADD CX,AX ; Add to Reserved Sectors
- MOV AX,FATBUF[17] ; Read Number of DIR Entries
- MOV RDIR_LEN,AX
- PUSH CX ; Calculate DIR Sectors
- MOV CL,5
- SHL AX,CL
- POP CX
- MOV BX,SECSIZE
- XOR DX,DX
- DIV BX
- OR DX,DX ; Adjust for Partial Sector
- JZ NO_ADD
- INC AX
- NO_ADD: MOV DIRSEC,AX ; Save DIR Sectors
- ADD CX,AX ; Add DIR Sectors to Reserved
- MOV STARTSEC,CX ; Save in STARTSEC
- MOV AX,FATSEC ; Determine FAT Buffer Size
- MOV BX,SECSIZE
- MUL BX
- ADD AX,OFFSET FATBUF
- MOV DIRBUF,AX ; Save DIRBUF Pointer
- MOV AX,FATBUF[19] ; Read Total Sectors on Media
- SUB AX,CX ; Calculate Total Data Clusters
- MOV BX,CLSTSEC
- XOR DX,DX
- DIV BX
- ADD AX,2
- MOV CLSTTOT,AX ; and Save
- CMP AX,4081 ; If Necessary, Adjust FAT Size
- JLE FAT_OK
- MOV FATSIZE,4
- MOV EOF,0FFF8H
- FAT_OK: MOV AL,DRIVE ; Read FAT
- MOV CX,FATSEC
- MOV DX,1
- MOV BX,OFFSET FATBUF
- INT 25H
- JC RDERROR ; If Error, Say So
- POPF
- MOV BX,CLUST ; Get Cluster Number
- MOV AX,BX ; Convert Cluster # to Decimal
- MOV DI,OFFSET CLUSTMSG[13]
- CALL DEC5OUT
- CALL STRIP0 ; Strip Off Leading Zeroes
- MOV AH,9
- MOV DX,OFFSET CLUSTMSG ; Output Cluster Message
- INT 21H
- CMP BX,CLSTTOT ; Test Cluster Number
- JNB CLSTBAD
- CMP BX,2
- JNB CLST_OK
- CLSTBAD: MOV DX,OFFSET INVALID ; If Invalid, Say So
- JMP SHORT ERROUT
- CLST_OK: CALL NEXTCLST ; Determine Next Cluster
- OR BX,BX ; If Not in Use, Say So
- JNZ NOT_FREE
- MOV DX,OFFSET FREEMSG
- JMP SHORT ERROUT
- NOT_FREE: MOV AX,EOF ; If In Use, Continue
- CMP BX,AX
- JAE CLSTGOOD
- DEC AX ; If Bad, Say So
- CMP BX,AX
- JNE NOT_BAD
- MOV DX,OFFSET BADMSG
- JMP SHORT ERROUT
- NOT_BAD: SUB AX,7 ; If Reserved, Say So
- CMP BX,AX
- JB CLSTGOOD
- MOV DX,OFFSET RESVMSG
- ERROUT: MOV AH,9 ; Output Error Message
- INT 21H
- MOV AX,4C01H ; Exit to DOS
- INT 21H
- RDERROR: POPF ; Handle Read Error
- MOV AL,DRIVE
- ADD AL,'A'
- MOV READERR[20],AL
- MOV DX,OFFSET READERR
- JMP SHORT ERROUT
- CLSTGOOD: MOV AX,CLUST ; Get Cluster Number
- CLSTBACK: MOV BX,AX ; Get Previous Cluster in Chain
- CALL PREVCLST
- OR AX,AX ; If Not First, Repeat
- JNZ CLSTBACK
- MOV CLUST,BX ; Save First Cluster in Chain
- LOOKHERE: CALL GETDIR ; Load the Current Directory
- CALL SRCHCLST ; Search Directory for Cluster
- JNC FOUND ; If Found, Exit Search Loop
- CALL SRCHDIR ; Search Dir for Sub-Directory
- JNC LOOKHERE ; If Found, Continue Search Loop
- CALL DIRNEXT ; Use Next Sub-Directory
- JNC LOOKHERE ; If Found, Continue Search Loop
- MOV DX,OFFSET LOSTMSG ; Else Couldn't find Cluster
- JMP ERROUT
- FOUND: MOV AL,DRIVE ; Convert Drive Number to Letter
- ADD AL,'A'
- MOV FILESPEC,AL
- MOV AH,9 ; Output Owner Message
- MOV DX,OFFSET OWNERMSG
- INT 21H
- MOV DX,OFFSET FILESPEC ; Output FileSpec
- INT 21H
- MOV DX,OFFSET FILENAME ; Output FileName
- INT 21H
- MOV DX,OFFSET CRLF
- INT 21H
- EXIT: MOV AX,4C00H ; Exit to DOS
- INT 21H
-
- DIRNEXT: PUSH AX ; Save Registers
- PUSH BX
- PUSH CX
- PUSH DI
- PUSH SI
- DIRNEXT1: MOV DI,OFFSET PATH ; Scan to End of Path
- MOV CX,80
- MOV AL,'$'
- REPNE SCASB
- JNE DIRNEXT3 ; If No End, Error
- CMP CX,79 ; If Null Path, Error
- JE DIRNEXT3
- STD ; Auto-Decrement
- MOV AX,78 ; Determine Path Length
- SUB AX,CX
- MOV CX,AX
- SUB DI,2 ; Point to End of DirName
- MOV AL,0 ; Set End of DirName
- STOSB
- MOV AL,'\' ; Scan to Previous DirName
- REPNE SCASB
- JE DIRNEXT2 ; If Not Found,
- MOV DI,OFFSET PATH[-2] ; Point to Start of Path
- DIRNEXT2: CLD ; Auto-Increment
- ADD DI,2 ; Copy Last SubDir to FileName
- PUSH DI
- MOV SI,DI
- MOV DI,OFFSET FILENAME
- CALL MOVSTR
- POP DI
- MOV AL,'$' ; Terminate Path String
- STOSB
- CALL GETDIR ; Read Directory
- JC DIRNEXT4 ; If Error, Say So
- MOV SI,OFFSET FILENAME
- MOV DI,OFFSET DIRNAME
- CALL MOVSTR
- CALL SRCHFILE ; Search for FileName
- JC DIRNEXT4 ; If Error, Say So
- MOV SI,BX ; Save Pointer
- ADD SI,32 ; Point to Next Dir Entry
- MOV AX,SI ; Determine Dir Entry Count
- SUB AX,DIRBUF
- MOV CL,5
- SHR AX,CL
- MOV CX,DIR_LEN
- SUB CX,AX
- CALL FINDDIR ; Find Next SubDirectory
- JC DIRNEXT1
- JMP SHORT DIRNEXT4
- DIRNEXT3: STC ; Set Error Return Flag
- DIRNEXT4: POP SI ; Restore Registers
- POP DI
- POP CX
- POP BX
- POP AX
- RET ; Done
-
- GETDIR: PUSH AX ; Save Registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
- MOV AL,DRIVE ; Read Root Directory
- MOV CX,DIRSEC
- MOV DX,STARTSEC
- SUB DX,CX
- MOV BX,DIRBUF
- INT 25H
- POPF
- MOV AX,RDIR_LEN ; DIR Length = Root DIR Length
- MOV DIR_LEN,AX
- MOV SI,OFFSET PATH ; Point to First Element of Path
- GETDIR1: MOV DI,OFFSET DIRNAME ; Point to FileName Buffer
- GETDIR2: LODSB ; Copy Path Element to FileName
- CMP AL,'\' ; until '\' or '$'
- JE GETDIR3
- CMP AL,'$'
- JE GETDIR4
- STOSB
- JMP SHORT GETDIR2
- GETDIR3: MOV AL,0 ; Read Subdirectory
- STOSB
- CALL READDIR
- JC GETDIR5 ; If Error, Say So
- JMP SHORT GETDIR1 ; Get Next Element
- GETDIR4: CLC ; Clear Error Flag
- GETDIR5: POP SI ; Restore Registers
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
- RET ; Done
-
- READDIR: PUSH CX ; Save Registers
- PUSH DI
- PUSH SI
- CALL SRCHFILE ; Search for DIR
- JC READDIR2 ; If Not Found, Error
- MOV BX,[BX+26] ; Get Starting Cluster Number
- MOV DIR_LEN,0 ; DIR Length = 0
- OR BX,BX ; If Start Cluster = 0, Error
- JZ READDIR2
- MOV AX,SECSIZE ; Calculate DIR Entries/Cluster
- MOV CX,CLSTSEC
- MUL CX
- MOV CL,5
- SHR AX,CL
- MOV CX,AX
- MOV DI,DIRBUF ; Point to DIR Buffer
- READDIR1: CALL READCLST ; Read Cluster
- ADD DIR_LEN,CX ; Increment DIR Length
- CMP BX,EOF ; If Not Last Cluster,
- JB READDIR1 ; Get Next Cluster
- JMP SHORT READDIR3 ; Done Reading DIR
- READDIR2: STC ; Set Error Flag
- READDIR3: POP SI ; Restore Registers
- POP DI
- POP CX
- RET ; Done
-
- SRCHDIR: PUSH CX ; Save Registers
- PUSH SI
- MOV SI,DIRBUF ; Point to First DIR Entry
- MOV CX,DIR_LEN ; Load DIR Length
- CALL FINDDIR ; Find SubDirectory
- POP SI ; Restore Registers
- POP CX
- RET ; Done
-
- FINDDIR: PUSH AX ; Save Registers
- PUSH DI
- FINDDIR1: JCXZ FINDDIR4 ; If Zero, Not Found
- FINDDIR2: CMP BYTE PTR [SI],'.' ; If '.' or '..', Skip
- JE FINDDIR3
- CMP BYTE PTR [SI],0E5H ; If Deleted, Skip
- JE FINDDIR3
- TEST BYTE PTR [SI+11],10H ; Test File Attribute
- JNZ FINDDIR5 ; If Match, Found
- FINDDIR3: ADD SI,32 ; Else Next DIR Entry
- LOOP FINDDIR2 ; and Repeat
- FINDDIR4: STC ; Set Error Flag
- JMP SHORT FINDDIR6 ; Done
- FINDDIR5: MOV DI,OFFSET DIRNAME
- CALL UNPARSE ; UnParse Directory Name
- MOV DI,OFFSET PATH ; Search for End of Path
- MOV AL,'$'
- MOV CX,80
- REPNE SCASB
- JNE FINDDIR4 ; If Not Found, Error
- DEC DI
- MOV BX,SI ; Set Pointer to DIR Entry
- MOV SI,OFFSET DIRNAME ; Copy Directory Name to Path
- CALL MOVSTR
- DEC DI
- MOV AX,'$\' ; Terminate Path
- STOSW
- CLC ; Clear Error Flag
- FINDDIR6: POP DI ; Restore Registers
- POP AX
- RET ; Done
-
- SRCHFILE: PUSH AX ; Save Register
- PUSH CX
- PUSH DI
- PUSH SI
- MOV AX,2900H ; Parse Filename
- MOV SI,OFFSET DIRNAME
- MOV DI,OFFSET FCB
- INT 21H
- INC DI ; Point to Filename in FCB
- MOV SI,DIRBUF ; Point to Start of DIRBUF
- MOV CX,DIR_LEN ; Load DIR Length
- JCXZ SRCHFIL2 ; If Zero, Not Found
- SRCHFIL1: PUSH CX ; Save Registers
- PUSH DI
- PUSH SI
- MOV CX,11 ; Compare Filename
- REPE CMPSB
- POP SI ; Restore Registers
- POP DI
- POP CX
- JE SRCHFIL3 ; If Match, Found
- ADD SI,32 ; Else Next DIR Entry
- LOOP SRCHFIL1 ; and Repeat
- SRCHFIL2: STC ; Set Error Flag
- JMP SHORT SRCHFIL4 ; Done
- SRCHFIL3: MOV BX,SI ; Set Pointer to DIR Entry
- CLC ; Clear Error Flag
- SRCHFIL4: POP SI ; Restore Registers
- POP DI
- POP CX
- POP AX
- RET ; Done
-
- SRCHCLST: PUSH AX ; Save Register
- PUSH CX
- PUSH DI
- PUSH SI
- MOV SI,DIRBUF ; Point to First DIR Entry
- MOV CX,DIR_LEN ; Load DIR Length
- JCXZ SRCHCLS3 ; If Zero, Not Found
- MOV BX,CLUST
- SRCHCLS1: CMP BYTE PTR [SI],'.' ; If '.' or '..', Skip
- JE SRCHCLS2
- CMP BYTE PTR [SI],0E5H ; If Deleted, Skip
- JE SRCHCLS2
- CMP BX,[SI+26] ; Compare Start Cluster Number
- JE SRCHCLS4 ; If Match, Found
- SRCHCLS2: ADD SI,32 ; Else Next DIR Entry
- LOOP SRCHCLS1 ; and Repeat
- SRCHCLS3: STC ; Set Error Flag
- JMP SHORT SRCHCLS5 ; Done
- SRCHCLS4: MOV DI,OFFSET FILENAME ; UnParse File Name
- CALL UNPARSE
- CLC ; Clear Error Flag
- SRCHCLS5: POP SI ; Restore Registers
- POP DI
- POP CX
- POP AX
- RET ; Done
-
- READCLST: PUSH AX ; Save Registers
- PUSH CX
- PUSH DX
- MOV AX,BX ; Calculate Absolute Sector #
- SUB AX,2
- MOV CX,CLSTSEC
- MUL CX
- ADD AX,STARTSEC
- MOV DX,AX
- MOV AL,DRIVE
- PUSH BX ; Save Registers
- PUSH DI
- MOV BX,DI ; Read Cluster
- INT 25H
- POPF
- POP DI ; Restore Registers
- POP BX
- CALL NEXTCLST ; Get Next Cluster Number
- MOV AX,CLSTSEC ; Increment Buffer Pointer
- MOV CX,SECSIZE
- MUL CX
- ADD DI,AX
- POP DX ; Restore Registers
- POP CX
- POP AX
- RET ; Done
-
- PREVCLST: PUSH BX ; Save Registers
- PUSH CX
- PUSH DX
- MOV DX,BX ; Reserve Cluster Number
- MOV CX,CLSTTOT ; Start Looking at Last Cluster
- PREVCLS1: MOV BX,CX ; Check Cluster
- INC BX
- CALL NEXTCLST
- CMP BX,DX ; If Match, Use It
- LOOPNE PREVCLS1 ; Else Repeat
- JNE PREVCLS2 ; If No Match, Return Zero
- ADD CX,2 ; Adjust for Cluster Number
- PREVCLS2: MOV AX,CX ; AX = Cluster Number
- POP DX ; Restore Registers
- POP CX
- POP BX
- RET ; Done
-
- NEXTCLST: CMP FATSIZE,3 ; If FAT Size = 16 Bits,
- JE NEXTCLS1
- SHL BX,1 ; Simply Read Next Cluster #
- MOV BX,FATBUF[BX]
- RET ; Done
- NEXTCLS1: PUSH AX ; Save Registers
- PUSH CX
- MOV AX,BX ; Word # = Cluster # * 1.5
- SHL AX,1
- ADD BX,AX
- SHR BX,1
- MOV BX,FATBUF[BX]
- JNC NEXTCLS2 ; If Odd, Use 12 MSB's
- MOV CL,4
- SHR BX,CL
- NEXTCLS2: AND BX,0FFFH ; Else Use 12 LSB's
- POP CX ; Restore Registers
- POP AX
- RET ; Done
-
- UNPARSE: PUSH CX ; Save Registers
- PUSH DI
- PUSH SI
- MOV CX,8 ; FileName Length = 8 Max
- UNPARSE1: LODSB ; Read Character
- CMP AL,' ' ; If Space, Exit Loop
- JE UNPARSE2
- STOSB ; Move Character
- LOOP UNPARSE1 ; Repeat
- UNPARSE2: MOV AL,'.' ; Put a Dot in the String
- STOSB
- POP SI ; Point to Extension
- PUSH SI
- ADD SI,8
- MOV CX,3 ; Extension Length = 3 Max
- UNPARSE3: LODSB ; Read Character
- CMP AL,' ' ; If Space, Exit Loop
- JE UNPARSE4
- STOSB ; Move Character
- LOOP UNPARSE3 ; Repeat
- UNPARSE4: CMP CX,3 ; If No Extension, Remove Dot
- JNE UNPARSE5
- DEC DI
- UNPARSE5: MOV AL,0 ; Terminate FileName
- STOSB
- MOV AL,'$'
- STOSB
- POP SI ; Restore Registers
- POP DI
- POP CX
- RET ; Done
-
- MOVSTR: LODSB ; Read Source
- STOSB ; Write Destination
- OR AL,AL ; If Not EOS, Repeat
- JNZ MOVSTR
- RET ; Done
-
- GET_WORD: PUSH BX ; Save Register
- XOR DX,DX ; Value = 0
- GET_WRD1: LODSB ; Read Character
- CMP AL,'0' ; If Not Numeric, Done
- JB GET_WRD2
- CMP AL,'9'
- JA GET_WRD2
- SUB AL,'0' ; Convert to BCD
- CBW
- MOV BX,AX ; Value = Value*10+BCD
- MOV AX,10
- MUL DX
- ADD AX,BX
- MOV DX,AX
- JMP GET_WRD1 ; Repeat
- GET_WRD2: DEC SI
- POP BX ; Restore Register
- RET ; Done
-
- STRIP0: CMP BYTE PTR [DI],'0' ; If Character != '0', Done
- JNE STRIP1
- CMP BYTE PTR [DI+1],'0' ; If Next Character != Digit,
- JL STRIP1 ; Done
- CMP BYTE PTR [DI+1],'9'
- JG STRIP1
- MOV BYTE PTR [DI],' ' ; Change '0' to ' '
- INC DI ; Point to Next Character
- JMP SHORT STRIP0 ; Repeat
- STRIP1: RET ; Done
-
- DEC2OUT: PUSH AX ; Save Registers
- PUSH BX
- XOR AH,AH ; Clear AH
- MOV BL,10 ; AH=AX%10,AL=AX/10
- DIV BL
- ADD AX,'00' ; Convert to ASCII
- SUB DI,2
- MOV [DI],AX ; Store in String
- POP BX ; Restore Registers
- POP AX
- RET ; Done
-
- DEC4OUT: PUSH AX ; Save Registers
- PUSH BX
- MOV BL,100 ; AH=AX%100,AL=AX/100
- DIV BL
- XCHG AH,AL ; Convert 2 LSD's
- CALL DEC2OUT
- XCHG AH,AL ; Convert 2 MSD's
- CALL DEC2OUT
- POP BX ; Restore Registers
- POP AX
- RET ; Done
-
- DEC5OUT: PUSH AX ; Save Registers
- PUSH BX
- PUSH DX ; DX=AX%10000,AX=AX/10000
- MOV BX,10000
- XOR DX,DX
- DIV BX
- XCHG DX,AX ; Convert 4 LSD's
- CALL DEC4OUT
- XCHG DX,AX ; Convert MSD
- ADD AL,'0'
- SUB DI,1
- MOV [DI],AL
- POP DX ; Restore Registers
- POP BX
- POP AX
- RET ; Done
-
- FATBUF LABEL WORD
-
- CODE ENDS
-
- END OWNER
-